package com.mineoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mineoj.common.ErrorCode;
import com.mineoj.exception.BusinessException;
import com.mineoj.model.entity.CompetitionJoin;
import com.mineoj.model.entity.Competition;
import com.mineoj.model.entity.CompetitionJoin;
import com.mineoj.model.entity.User;
import com.mineoj.service.CompetitionJoinService;
import com.mineoj.mapper.CompetitionJoinMapper;
import com.mineoj.service.CompetitionService;
import com.mineoj.service.CompetitionJoinService;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
* @author 明月
* @description 针对表【competition_join(比赛参加)】的数据库操作Service实现
* @createDate 2025-04-20 18:59:17
*/
@Service
public class CompetitionJoinServiceImpl extends ServiceImpl<CompetitionJoinMapper, CompetitionJoin>
    implements CompetitionJoinService{
    @Resource
    private CompetitionService competitionService;

    /**
     * 参赛
     *
     * @param competitionId
     * @param loginUser
     * @return
     */
    @Override
    public int doCompetitionJoin(long competitionId, User loginUser) {
        // 判断实体是否存在，根据类别获取实体
        Competition competition = competitionService.getById(competitionId);
        if (competition == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 是否已参赛
        long userId = loginUser.getId();

        // 锁必须要包裹住事务方法
        CompetitionJoinService competitionThumbService = (CompetitionJoinService) AopContext.currentProxy();
        synchronized (String.valueOf(userId).intern()) {
            return competitionThumbService.doCompetitionJoinInner(userId, competitionId);
        }
    }

    /**
     * 封装了事务的方法
     *
     * @param userId
     * @param competitionId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int doCompetitionJoinInner(long userId, long competitionId) {
        CompetitionJoin competitionThumb = new CompetitionJoin();
        competitionThumb.setUserId(userId);
        competitionThumb.setCompetitionId(competitionId);
        QueryWrapper<CompetitionJoin> thumbQueryWrapper = new QueryWrapper<>(competitionThumb);
        CompetitionJoin oldCompetitionJoin = this.getOne(thumbQueryWrapper);
        boolean result;
        // 已参赛
        if (oldCompetitionJoin != null) {
            // 不能重复参赛
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "不能重复参赛");
        } else {
            // 未参赛
            result = this.save(competitionThumb);
            if (result) {
                // 参赛数 + 1
                result = competitionService.update()
                        .eq("id", competitionId)
                        .setSql("joinNum = joinNum + 1")
                        .update();
                return result ? 1 : 0;
            } else {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
        }
    }

}




